﻿/* 项目名称： WindowsManager.cs
 * 命名空间： Vampirewal.Core.SimpleMVVM
 * 类 名 称: WindowsManager
 * 作   者 : 杨程
 * 概   述 :
 * 创建时间 : 2021/2/20 18:47:33
 * 更新时间 : 2021/2/20 18:47:33
 * CLR版本 : 4.0.30319.42000
 * ******************************************************
 * Copyright@Administrator 2021 .All rights reserved.
 * ******************************************************
 */

namespace Vampirewal.Core.SimpleMVVM;

/// <summary>
/// 窗体管理
/// </summary>
public sealed class WindowsManager : BaseSingleton<WindowsManager>
{
    private WindowCollection windows = new WindowCollection();

    /// <summary>
    /// 主窗体(方便弹窗使用)
    /// </summary>
    public IWindows MainWindow { get; set; }

    /// <summary>
    /// 获取已创建的窗口
    /// </summary>
    public WindowCollection Windows
    {
        get { return windows; }
    }

    private Dictionary<Guid, IWindows> DialogWindowDic { get; set; } = new Dictionary<Guid, IWindows>();

    /// <summary>
    /// 关闭所有窗口
    /// </summary>
    [Obsolete("这里还存在异常，先作废",true)]
    public void CloseAllWindow()
    {
        var appService= VampirewalCoreContext.GetInstance().GetService<IApplicationService>();

        if(appService != null)
        {
            appService.Shutdown();
        }

        //foreach (var window in windows)
        //{
        //    window.Close();
        //}
    }

    /// <summary>
    /// 关闭DialogWindow窗体
    /// </summary>
    /// <param name="ViewId"></param>
    public void CloseDialogWindow(Guid ViewId)
    {
        if (DialogWindowDic.TryGetValue(ViewId, out IWindows window))
        {
            try
            {
                var DialogWindow = window as IDialogWindow;
                var vm = DialogWindow.DataContext as ViewModelBase;
                DialogWindow.CloseDialogWindowCallBackCommand?.Execute(vm.GetResult());
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                window.Close();
                DialogWindowDic.Remove(ViewId);
            }
        }
    }

    /// <summary>
    /// 关闭窗体
    /// </summary>
    /// <param name="ViewId">窗体ID</param>
    public void CloseWindow(Guid ViewId)
    {
        var win = windows.FirstOrDefault(f => f.ViewId == ViewId);
        if (win != null)
        {
            windows.Remove(win);
            win.Close();
        }
        else
        {
            CloseDialogWindow(ViewId);
        }

        GC.Collect();
    }

    /// <summary>
    /// 获取DialogWindow窗体
    /// </summary>
    /// <param name="ViewId"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public IWindows GetDialogWindow(Guid ViewId)
    {
        if (DialogWindowDic.TryGetValue(ViewId, out IWindows window))
        {
            return window;
        }
        else
        {
            throw new WindowsManagerException("未找到对应DialogWindow");
        }
    }

    /// <summary>
    /// 获取Window窗体
    /// </summary>
    /// <param name="ViewId"></param>
    /// <returns></returns>
    public IWindows GetWindow(Guid ViewId)
    {
        return windows.FirstOrDefault(f => f.ViewId == ViewId);
    }

    /// <summary>
    /// 获取当前启用窗体
    /// </summary>
    /// <returns></returns>
    public IWindows GetActivateWindows()
    {
        var win= windows.FirstOrDefault(f => f.Activate());
        if (win == null)
        {
            win = DialogWindowDic.FirstOrDefault(w => w.Value.Activate()).Value;
        }

        return win;
    }


    /// <summary>
    /// 获取窗体并指定VM和传参
    /// </summary>
    /// <param name="ViewToken"></param>
    /// <param name="ViewModelToken"></param>
    /// <param name="Param"></param>
    /// <returns></returns>
    public IUcViewBase GetView(string ViewToken, string ViewModelToken = "", object Param = null)
    {
        return GetViewBase(ViewToken, ViewModelToken, Param);
    }

    /// <summary>
    /// Window窗体以Dialog方式打开并获取返回值
    /// </summary>
    /// <param name="ViewToken"></param>
    /// <param name="ViewModelToken"></param>
    /// <param name="Param"></param>
    /// <param name="IsMainWindow">是否设置为主窗体</param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public object OpenDialogWindow(string ViewToken, string ViewModelToken = "", object Param = null, bool IsMainWindow = false)
    {
        var w = GetWindowBase(ViewToken, ViewModelToken, Param, IsMainWindow);

        w.ShowDialog();

        return w.DataSource.GetResult();
    }

    /// <summary>
    /// 打开Window窗体并传入参数到VM中
    /// </summary>
    /// <param name="ViewToken"></param>
    /// <param name="ViewModelPath"></param>
    /// <param name="Param"></param>
    /// <param name="IsMainWindow">是否设置为主窗体</param>
    public void OpenWindow(string ViewToken, string ViewModelPath = "", object Param = null, bool IsMainWindow = false)
    {
        GetWindowBase(ViewToken, ViewModelPath, Param, IsMainWindow).Show();
    }

    /// <summary>
    /// 打开window窗体并获取返回值
    /// </summary>
    /// <param name="ViewToken">窗体Token</param>
    /// <param name="ViewModelPath"></param>
    /// <param name="Param"></param>
    /// <param name="IsMainWindow">是否设置为主窗体</param>
    /// <returns></returns>
    public object OpenWindowGetResult(string ViewToken, string ViewModelPath = "", object Param = null, bool IsMainWindow = false)
    {
        var win = GetWindowBase(ViewToken, ViewModelPath, Param, IsMainWindow);

        win.Show();

        return win.DataSource.GetResult();
    }

    /// <summary>
    /// 注册DialogWindow窗体
    /// </summary>
    /// <param name="ViewId"></param>
    /// <param name="window"></param>
    public bool RegisterDialogWindow(Guid ViewId, IWindows window)
    {
        return DialogWindowDic.TryAdd(ViewId, window);
    }

    /// <summary>
    /// 注册存储window
    /// </summary>
    /// <param name="w"></param>
    public void RegisterWindow(IWindows w)
    {
        if (!Windows.Contains(w))
        {
            windows.Add(w);
        }
    }

    private IUcViewBase GetViewBase(string ViewToken, string ViewModelToken, object Param = null)
    {
        if (string.IsNullOrEmpty(ViewToken))
            throw new WindowsManagerException("窗体Token不能为空！");

        try
        {
            var view = VampirewalCoreContext.GetInstance().GetView<IUcViewBase>(ViewToken) ?? throw new WindowsManagerException("窗体未找到！");
            ViewModelBase VM = null;

            if (!string.IsNullOrEmpty(view.ViewModelKey))
            {
                VM = VampirewalCoreContext.GetInstance().GetViewModel<ViewModelBase>(view.ViewModelKey);
            }
            else if (!string.IsNullOrEmpty(ViewModelToken))
            {
                VM = VampirewalCoreContext.GetInstance().GetViewModel<ViewModelBase>(ViewModelToken);
            }

            if (VM == null)
                throw new WindowsManagerException("对应ViewModelKey未找到！");

            VM.InitData();
            VM.MessengerRegister();

            if (Param != null)
                VM.PassData(Param);

            view.DataContext = VM;
            view.DataSource = VM;
            VM.ViewId = view.ViewId;

            return view;
        }
        catch (WindowsManagerException ex)
        {
            throw ex;
        }
    }

    /// <summary>
    /// 获取窗体
    /// </summary>
    /// <param name="ViewToken"></param>
    /// <param name="ViewModelToken"></param>
    /// <param name="Param"></param>
    /// <param name="IsMainWindow"></param>
    /// <returns></returns>
    /// <exception cref="WindowsManagerException"></exception>
    private IWindows GetWindowBase(string ViewToken, string ViewModelToken = "", object Param = null, bool IsMainWindow = false)
    {
        if (string.IsNullOrEmpty(ViewToken))
            throw new WindowsManagerException("窗体Token不能为空！");

        try
        {
            var window = VampirewalCoreContext.GetInstance().GetView<IWindows>(ViewToken) ?? throw new WindowsManagerException("窗体未找到！");
            ViewModelBase VM = null;

            if (!string.IsNullOrEmpty(window.ViewModelKey))
            {
                VM = VampirewalCoreContext.GetInstance().GetViewModel<ViewModelBase>(window.ViewModelKey);
            }
            else if (!string.IsNullOrEmpty(ViewModelToken))
            {
                VM = VampirewalCoreContext.GetInstance().GetViewModel<ViewModelBase>(ViewModelToken);
            }

            if (VM == null)
                throw new WindowsManagerException("对应ViewModelKey未找到！");

            VM.InitData();
            VM.MessengerRegister();

            if (Param != null)
                VM.PassData(Param);

            window.DataContext = VM;
            window.DataSource = VM;
            //window.DataSource.view = window;
            VM.ViewId = window.ViewId;
            windows.Add(window);

            if (IsMainWindow)
            {
                MainWindow = window;
            }

            return window;
        }
        catch (WindowsManagerException ex)
        {
            throw ex;
        }
    }
}

/// <summary>
///
/// </summary>
[Serializable]
public class WindowsManagerException : Exception
{
    /// <summary>
    ///
    /// </summary>
    /// <param name="mes"></param>
    public WindowsManagerException(string mes) : base(mes)
    {
    }
}